package com.example.springaop.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Aspect// 表示当前类是一个切面
@Component// component - 组件 - 我们的 切面 不就像是“组件”嘛。起着某种作用。
public class UserAspect {

    @Pointcut("execution(* com.example.springaop.controller.UserController.*(..))")
    public void pointcut() {

    }

    @Before("pointcut()")// 注解中参数，就是在声明这个 前置方法是针对哪个切点的
    public void doBefore(){
        System.out.println("前置通知：被执行了");
    }

    @After("pointcut()")
    public void doAfter(){
        System.out.println("后置通知：被执行了");
    }

    @AfterReturning("pointcut()")
    public void doAfterReturning(){
        System.out.println("执行了 AfterReturning 方法");
    }

    @AfterThrowing("pointcut()")
    public void doAfterThrowing(){
        System.out.println("执行了 AfterThrowing 方法");
    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint){
        // spring 中的时间统计对象
        StopWatch stopWatch = new StopWatch();

        Object o = null;
//        System.out.println("环绕通知的前置方法，被执行了");
        try {
            // 统计方法 的 执行时间，开始计时了
            stopWatch.start();
            // 执行目标方法
            o = joinPoint.proceed();
            // 统计方法 的 执行时间，停止计时了
            stopWatch.stop();
        } catch (Throwable e) {
            e.printStackTrace();
        }
//        System.out.println("环绕通知的后置方法，被执行了");
        System.out.println(joinPoint.getSignature().getDeclaringType()
                + "."
                + joinPoint.getSignature().getName() + "方法执行花费的时间："
                + stopWatch.getTotalTimeMillis() + "ms");
        return o;
    }
}
